﻿Imports System.Linq
Imports System.Collections.Generic
Imports SISSAT.BusinessLayer.Services
Imports SISSAT.BusinessLayer.DomainModels

Namespace Managers
    Public Class GradePointManager
        Inherits ServiceBase

        Private Property ExaminationService As IExaminationService
        Private Property ExaminationTypeService As IExaminationTypeService
        Private Property EmployeeService As IEmployeeService
        Private Property EmployeeId As Integer

        Public Sub New(currentUserId As Integer)
            Me.ExaminationService = New ExaminationService
            Me.ExaminationTypeService = New ExaminationTypeService
            Me.EmployeeService = New EmployeeService
            Me.EmployeeId = currentUserId
        End Sub

        Public Shared Function GradePointConversion(percentage As Decimal) As Decimal
            Dim gradePoint As Decimal = 5D

            If (percentage > 98D) Then
                gradePoint = 1D
            ElseIf (percentage > 95D) Then
                gradePoint = 1.25D
            ElseIf (percentage > 92D) Then
                gradePoint = 1.5D
            ElseIf (percentage > 89D) Then
                gradePoint = 1.75D
            ElseIf (percentage > 86D) Then
                gradePoint = 2D
            ElseIf (percentage > 83D) Then
                gradePoint = 2.25D
            ElseIf (percentage > 80D) Then
                gradePoint = 2.5D
            ElseIf (percentage > 77D) Then
                gradePoint = 2.75D
            ElseIf (percentage > 74D) Then
                gradePoint = 3D
            ElseIf (percentage = 0D) Then
                gradePoint = 7D
            End If

            Return gradePoint
        End Function

        Public Sub ComputeGrade(studentCode As String, scheduleId As Integer, groupId As Integer)
            Dim examinations As IEnumerable(Of Examination) = ExaminationService.ReadAll(studentCode, scheduleId, groupId)
            Dim count As Integer = examinations.Count()

            If count < 8 Then
                Return
            End If

            Dim attendance As Decimal = _
                (From exam In examinations Where exam.ExaminationType.GroupId = 1 Select exam.Grade).FirstOrDefault()
            Dim assignments As Decimal = _
                (From exam In examinations Where exam.ExaminationType.GroupId = 2 Select exam.Grade).Sum()
            Dim quizzes As Decimal = _
                (From exam In examinations Where exam.ExaminationType.GroupId = 3 Select exam.Grade).Sum()
            Dim majorExam As Decimal = _
                (From exam In examinations Where exam.ExaminationType.GroupId = 4 Select exam.Grade).Sum()

            If attendance = 0D OrElse assignments = 0D OrElse quizzes = 0D OrElse majorExam = 0D Then
                Return
            End If

            attendance = ((Convert.ToDecimal(attendance) / 4D) * 50D) + 50D
            assignments = Convert.ToDecimal(assignments / 3D)
            quizzes = Convert.ToDecimal((quizzes / (300D) * 60D) + 40)
            majorExam = ((Convert.ToDecimal(majorExam) / 100D) * 60D) + 40D

            Dim gradePoint As Decimal = 0D

            If groupId = 12 Then
                gradePoint = (attendance * 0.1D) + (assignments * 0.1D) + (quizzes * 0.2D) + (majorExam * 0.6D)
            Else
                gradePoint = (attendance * 0.1D) + (assignments * 0.3D) + (quizzes * 0.2D) + (majorExam * 0.4D)
            End If

            Dim examination As Examination = ExaminationService.ReadByStudentCode(studentCode, scheduleId, groupId, groupId)
            Dim table As DataTable = examination.GetDataTable()

            If examination Is Nothing Then
                table.Rows.Add(0, scheduleId, groupId, groupId, studentCode, gradePoint)
                ExaminationService.Create(table, Me.EmployeeId)
            Else
                examination.Grade = gradePoint
                table.Rows.Add(examination.ExaminationId, examination.Schedule.ScheduleId, examination.ExaminationType.ExaminationTypeId, examination.GroupId, examination.StudentCode, examination.Grade)
                ExaminationService.Edit(table, Me.EmployeeId)
            End If

            ComputeGradePointAverage(studentCode, scheduleId)
        End Sub

        Private Sub ComputeGradePointAverage(studentCode As String, scheduleId As Integer)
            Dim exams As IEnumerable(Of Examination) = _
                ExaminationService.ReadAllFilteredByMajorExams(studentCode, scheduleId)
            Dim count As Integer = exams.Count()

            If count < 4 Then
                Return
            End If

            Dim preliminary As Decimal = _
                (From exam In exams Where exam.ExaminationType.ExaminationTypeId = 9 Select exam.Grade).FirstOrDefault()
            Dim midTerm As Decimal = _
                (From exam In exams Where exam.ExaminationType.ExaminationTypeId = 10 Select exam.Grade).FirstOrDefault()
            Dim preFinals As Decimal = _
                (From exam In exams Where exam.ExaminationType.ExaminationTypeId = 11 Select exam.Grade).FirstOrDefault()
            Dim finals As Decimal = _
                (From exam In exams Where exam.ExaminationType.ExaminationTypeId = 12 Select exam.Grade).FirstOrDefault()

            midTerm = (midTerm * 0.6D) + (preliminary * 0.4D)
            preFinals = (preFinals * 0.6D) + (midTerm * 0.4D)
            finals = (finals * 0.8D) + (preFinals * 0.2D)
            Dim gradePoint As Decimal = GradePointManager.GradePointConversion(finals)

            Dim employee As Employee = EmployeeService.ReadByCode(studentCode)

            Dim matriculationService As IMatriculationService = New MatriculationService
            matriculationService.Edit(employee.EmployeeId, scheduleId, gradePoint, Me.EmployeeId)
        End Sub

    End Class
End Namespace

